package com.aidex.biz.service.impl;

import com.aidex.biz.domain.RubbishType;
import com.aidex.biz.domain.vo.RubbishTypeEls;
import com.aidex.biz.mapper.RubbishTypeMapper;
import com.aidex.biz.service.RubbishTypeService;
import com.aidex.common.annotation.DataScope;
import com.aidex.common.constant.Constants;
import com.aidex.common.constant.UserConstants;
import com.aidex.common.core.domain.BaseEntity;
import com.aidex.common.core.domain.TreeNode;
import com.aidex.common.core.service.BaseTreeServiceImpl;
import com.aidex.common.exception.BizException;
import com.aidex.common.exception.SysException;
import com.aidex.common.utils.NumberUtils;
import com.aidex.common.utils.PinYin4JCn;
import com.aidex.common.utils.StringUtils;
import com.aidex.common.utils.reflect.ReflectUtils;
import com.aidex.common.utils.uuid.IdUtils;
import com.aidex.system.common.SysErrorCode;
import com.alibaba.fastjson.JSONObject;
import org.springframework.stereotype.Service;
import org.springframework.util.CollectionUtils;

import java.util.*;

/**
 * 分类管理 服务实现
 *
 * @author ruoyi
 */
@Service
public class RubbishTypeServiceImpl extends BaseTreeServiceImpl<RubbishTypeMapper, RubbishType> implements RubbishTypeService {


    private static final int ID_LIMIT = 500;

    /**
     * 新增保存分类信息
     *
     * @return 结果
     */
    @Override
    public boolean save(RubbishType sysRubbishType) {
        checkRubbishTypeNameUnique(sysRubbishType);
        RubbishType parentRubbishType = mapper.get(sysRubbishType.getParentId());
        sysRubbishType.setDeptPinyin(PinYin4JCn.getFullAndSimplePinYin(sysRubbishType.getDeptName(), 500));
        if (null != parentRubbishType || StringUtils.isNotBlank(sysRubbishType.getId())) {
            //没有父节点或者当前数据有ID(编辑跟节点时)
            //新增
            if (StringUtils.isEmpty(sysRubbishType.getId())) {
                // 如果父节点不为正常状态,则不允许新增子节点
                if (!UserConstants.DEPT_NORMAL.equals(parentRubbishType.getStatus())) {
                    throw new BizException(SysErrorCode.B_SYSDEPT_DeptAlreadyUnNormal, "停用，不允许新增子分类");
                }
                setTreeProperties(sysRubbishType, null, Constants.OpType.insert);
                super.save(sysRubbishType);
            } else {
                //编辑
                RubbishType oldRubbishType = mapper.get(sysRubbishType);
                if (isMoveToSelfChildNode(sysRubbishType, oldRubbishType)) {
                    throw new BizException(SysErrorCode.B_SYSDEPT_DeptMoveUnNormal, "非法移动，不允许将节点移动到自身或者子节点下");
                }
                List<RubbishType> updateChildList = new ArrayList<RubbishType>();
                if (sysRubbishType.getParentId().equals(sysRubbishType.getId())) {
                    throw new BizException(SysErrorCode.B_SYSDEPT_DeptIdNotEqualParentId, "修改分类失败，上级分类不能是自己");
                }
                if (StringUtils.equals(UserConstants.DEPT_DISABLE, sysRubbishType.getStatus()) && mapper.selectNormalChildByParentIds(sysRubbishType.getParentIds()) > 0) {
                    throw new BizException(SysErrorCode.B_SYSDEPT_DeptHasNormalChild, "该分类包含未停用的子分类，不允许标记为停用");
                }
                if ("dept".equals(sysRubbishType.getDeptType())) {
                    //当修改类型为分类时需要判断当前节点下所有子孙节点中是否存在公司节点
//                    RubbishType checkRubbishType = sysRubbishType;//避免对象引用
                    RubbishType checkRubbishType = new RubbishType();
                    checkRubbishType.setId(sysRubbishType.getId());
                    checkRubbishType.setDeptType("company");
                    List<RubbishType> checkList = mapper.searchChildrenTypeByParentId(checkRubbishType);
                    if (!CollectionUtils.isEmpty(checkList)) {
                        throw new BizException(SysErrorCode.B_SYSDEPT_NoAllowUpdateType);
                    }
                }
                if (isUpdateTreeProperties(sysRubbishType, oldRubbishType)) {
                    setTreeProperties(sysRubbishType, oldRubbishType, Constants.OpType.update);
                    updateChildList = updateChildTreeProperties(sysRubbishType, oldRubbishType);
                    if (!CollectionUtils.isEmpty(updateChildList)) {
                        mapper.updateRubbishTypeChildren(updateChildList);
                    }
                }
                parentRubbishType = mapper.get(sysRubbishType.getParentId());
                // 新的父节点变更为非叶子节点
                if (!Constants.TREE_ROOT.equals(sysRubbishType.getParentId()) && parentRubbishType.getTreeLeaf().equals(Constants.TREE_LEAF_Y)) {
                    parentRubbishType.setTreeLeaf(Constants.TREE_LEAF_N);
                    super.save(parentRubbishType);
                }
                String oldParentId = oldRubbishType.getParentId();
                super.save(sysRubbishType);
                // 判断原节点是否还有子节点，否则改为叶子节点
                if (!hasChildByRubbishTypeId(oldParentId)) {
                    RubbishType oldParentRubbishType = mapper.get(oldParentId);
                    oldParentRubbishType.setTreeLeaf(Constants.TREE_LEAF_Y);
                    super.save(oldParentRubbishType);
                }
            }
        } else {
            //新增根节点
            sysRubbishType.setId(IdUtils.randomUUID());
            sysRubbishType.setNewRecord(true);
            sysRubbishType.setParentIds(sysRubbishType.getId());
            // 设置当前树全路径排序
            Integer treeSort = sysRubbishType.getTreeSort();
            String treeSorts = String.format("%06d", treeSort);
            sysRubbishType.setTreeSorts(treeSorts);
            sysRubbishType.setTreeLeaf(Constants.TREE_LEAF_Y);
            // 设置当前节点级别.
            sysRubbishType.setTreeLevel(1);
            super.save(sysRubbishType);
        }
        return Boolean.TRUE;
    }

    /**
     * 删除分类
     *
     * @param sysRubbishType
     * @return
     */
    @Override
    public boolean remove(RubbishType sysRubbishType) {
        sysRubbishType = mapper.get(sysRubbishType.getId());
        //删除
        super.remove(sysRubbishType);
        //判断当前父节点下还是否有子节点，如果没有，则需要把父节点置为叶子节点
        RubbishType parentRubbishType = mapper.get(sysRubbishType.getParentId());

        if (null!=parentRubbishType&&findChildCountById(sysRubbishType.getParentId()) == 0) {
            parentRubbishType.setTreeLeaf(Constants.TREE_LEAF_Y);
            super.save(parentRubbishType);
        }
        return Boolean.TRUE;
    }

    public Integer findChildCountById(String sysRubbishTypeId) {
        RubbishType sysRubbishType = new RubbishType();
        sysRubbishType.setParentId(sysRubbishTypeId);
        return mapper.findCount(sysRubbishType);
    }

    /**
     * 查询最大排序号
     *
     * @param sysRubbishType
     * @return
     */
    @Override
    public Integer findMaxSort(RubbishType sysRubbishType) {
        return NumberUtils.nextOrder(mapper.findMaxSort(sysRubbishType));
    }

    /**
     * 是否存在子节点
     *
     * @param sysRubbishTypeId 分类ID
     * @return 结果
     */
    @Override
    public boolean hasChildByRubbishTypeId(String sysRubbishTypeId) {
        int result = findChildCountById(sysRubbishTypeId);
        return result > 0;
    }

    /**
     * 查询分类是否存在用户
     *
     * @param deptId 分类ID
     * @return 结果 true 存在 false 不存在
     */


    /**
     * 校验分类名称是否唯一
     *
     * @param dept 分类信息
     * @return 结果
     */
    @Override
    public void checkRubbishTypeNameUnique(RubbishType dept) {
        RubbishType sysRubbishTypeUnique = new RubbishType();
        sysRubbishTypeUnique.setNotEqualId(dept.getId());
        sysRubbishTypeUnique.setDeptName(dept.getDeptName());
        sysRubbishTypeUnique.setParentId(dept.getParentId());
        if (!CollectionUtils.isEmpty(mapper.findListWithUnique(sysRubbishTypeUnique))) {
            throw new BizException(SysErrorCode.B_SYSDEPT_DeptNameAlreadyExist);
        }
    }

    /**
     * 根据展开层级和父节点递归获取展示的数据
     *
     * @param level
     * @param parentId
     * @return
     */
    @Override
//    @DataScope(deptAlias = "t", userAlias = "t")
    public List<RubbishType> listDataByLevel(RubbishType sysRubbishType, int level, String parentId) {
        List<RubbishType> listData = new ArrayList<RubbishType>();
        level--;
        List<RubbishType> childrenList = findChildListByParentId(parentId, sysRubbishType);
        for (RubbishType dto : childrenList) {
            if ("n".equals(dto.getTreeLeaf()) && level > 0) {
                dto.setChildren(this.listDataByLevel(sysRubbishType, level, dto.getId()));
            } else {
                dto.setChildren(new ArrayList<>());
            }
            listData.add(dto);
        }
        return listData;
    }


    /**
     * 构建前端所需要树结构
     *
     * @param level    展开层级
     * @param parentId 父节点ID
     * @return
     */
    @Override
    @DataScope(deptAlias = "t", userAlias = "t")
    public List<TreeNode> buildRubbishTypeTree(RubbishType sysRubbishType, int level, String parentId) {
        return this.buildRubbishTypeTreeExcludeChild(sysRubbishType, level, parentId, "");
    }

    /**
     * 构建前端所需要树结构
     *
     * @param level     展开层级
     * @param parentId  父节点ID
     * @param excludeId 排除节点ID
     * @return
     */
    @Override
    public List<TreeNode> buildRubbishTypeTreeExcludeChild(RubbishType dept, int level, String parentId,
            String excludeId) {
        List<TreeNode> listData = new ArrayList<TreeNode>();
        level--;
        List<RubbishType> childrenList = findChildListByParentId(parentId, dept);
        for (RubbishType sysRubbishType : childrenList) {
            if (!sysRubbishType.getId().equals(excludeId)) {
                TreeNode treeNode = this.transToTreeNodeData(sysRubbishType);
                if ("n".equals(sysRubbishType.getTreeLeaf()) && level != 0) {
                    treeNode.setChildren(this.buildRubbishTypeTreeExcludeChild(dept, level, sysRubbishType.getId(),
                            excludeId));
                } else {
                    treeNode.setChildren(null);
                }
                //不展开节点的父节点数据处理
                if (CollectionUtils.isEmpty(treeNode.getChildren())) {
                    treeNode.setChildren(null);
                }
                listData.add(treeNode);
            }
        }
        return listData;
    }

    /**
     * 根据父ID查询子节点
     *
     * @param parentId 父ID
     * @return
     */
    public List<RubbishType> findChildListByParentId(String parentId, RubbishType rubbishType) {
        Class<RubbishType> entityClass = ReflectUtils.getClassGenricType(getClass(), 1);
        RubbishType entity = null;
        try {
            entity = entityClass.getConstructor().newInstance();
        } catch (Exception e) {
            e.printStackTrace();
            throw new SysException(e.getMessage());
        }
        entity.setParentId(parentId);
        entity.setParams(rubbishType.getParams());
        entity.setIsIndex(rubbishType.getIsIndex());
        entity.setCompanyId(rubbishType.getCompanyId());
        entity.setBusType(rubbishType.getBusType());
        return mapper.findList(entity);
    }

    /**
     * 组建树形结构
     *
     * @param entityNodes 节点集合
     * @return List<VueNode>
     */
    private List<RubbishType> createTreeGridData(List<RubbishType> entityNodes) {
        List<RubbishType> treeList = new ArrayList<RubbishType>();
        for (RubbishType sysRubbishType : entityNodes) {
            //找到根节点
            if (Constants.TREE_ROOT.equals(sysRubbishType.getParentId())) {
                treeList.add(sysRubbishType);
            }
            List<RubbishType> children = new ArrayList<RubbishType>();
            //再次遍历list，找到子节点
            for (RubbishType node : entityNodes) {
                if (node.getParentId().equals(sysRubbishType.getId())) {
                    children.add(node);
                }
            }
            sysRubbishType.setChildren(children);
            if (children.isEmpty()) {
                sysRubbishType.setTreeLeaf("y");
            } else {
                sysRubbishType.setTreeLeaf("n");
            }
        }
        return treeList;
    }

    /**
     * 根据parentIds去重
     *
     * @param entityNodes entityNodes
     */
    private Set<String> reDuplicationByTreePath(List<RubbishType> entityNodes) {
        Set<String> treeIdSet = new HashSet<String>();
        for (RubbishType dto : entityNodes) {
            String treePath = dto.getParentIds();
            treeIdSet.addAll(Arrays.asList(treePath.split("/")));
        }
        return treeIdSet;
    }

    /**
     * 组建树形结构
     *
     * @param entityNodes 节点集合
     * @return List<VueNode>
     */
    private List<TreeNode> createTreeData(List<RubbishType> entityNodes) {
        List<TreeNode> list = transToTreeNodeData(entityNodes);
        List<TreeNode> tree = new ArrayList<TreeNode>();
        for (TreeNode treeNode : list) {
            //找到根节点
            if (Constants.TREE_ROOT.equals(treeNode.getParentId())) {
                tree.add(treeNode);
            }
            List<TreeNode> children = new ArrayList<TreeNode>();
            //再次遍历list，找到子节点
            for (TreeNode node : list) {
                if (node.getParentId().equals(treeNode.getId())) {
                    children.add(node);
                }
            }
            treeNode.setChildren(children);
            if (children.isEmpty()) {
                treeNode.setIsLeaf(true);
            }
        }
        return tree;
    }

    /**
     * 将实体类集合转化成VueNode格式
     *
     * @param entityNodes 实体类节点集合
     * @return List<VueNode>
     */
    private List<TreeNode> transToTreeNodeData(List<RubbishType> entityNodes) {
        List<TreeNode> treeNodes = new ArrayList<TreeNode>();
        for (RubbishType entityNode : entityNodes) {
            TreeNode treeNode = transToTreeNodeData(entityNode);
            treeNodes.add(treeNode);
        }
        return treeNodes;
    }

    /**
     * 将实体类转化成VueNode格式
     *
     * @param entityNode 实体类节点集合
     * @return List<VueNode>
     */
    private TreeNode transToTreeNodeData(RubbishType entityNode) {
        TreeNode treeNode = new TreeNode();
        treeNode.setId(entityNode.getId());
        treeNode.setKey(entityNode.getId());
        treeNode.setTitle(entityNode.getDeptName());
        treeNode.setLabel(entityNode.getDeptName());
        treeNode.setSelectable(true);
        treeNode.setDisabled(false);
        treeNode.setDisableCheckbox(false);
        treeNode.setParentId(entityNode.getParentId());
        treeNode.setParentIds(entityNode.getParentIds());
        HashMap<String, Object> attr = new HashMap<>();
        attr.put("treeLeaf", entityNode.getTreeLeaf());
        attr.put("treeLevel", entityNode.getTreeLevel());
        attr.put("treePath", entityNode.getParentIds());
        attr.put("deptType", entityNode.getDeptType());

        attr.put("deptPinyin", entityNode.getDeptPinyin());
        treeNode.setAttributes(attr);
        if (Constants.TREE_LEAF_Y.equals(entityNode.getTreeLeaf())) {
            treeNode.setIsLeaf(true);
        } else {
            treeNode.setIsLeaf(false);
        }
        JSONObject slotsValue = new JSONObject();
        String deptType = StringUtils.isNotBlank(entityNode.getDeptType()) ? entityNode.getDeptType() : "";
        if ("org".equals(deptType)) {
            slotsValue.put("icon", "org");
            treeNode.setDisableCheckbox(true);
        } else if ("company".equals(deptType)) {
            slotsValue.put("icon", "company");
            treeNode.setDisableCheckbox(true);
        } else if ("dept".equals(deptType)) {
            slotsValue.put("icon", "dept");
            treeNode.setDisableCheckbox(false);
        } else if ("user".equals(deptType)) {
            slotsValue.put("icon", "user");
            treeNode.setDisableCheckbox(false);
        }
        JSONObject scopedSlotsValue = new JSONObject();
        scopedSlotsValue.put("title", "title");
        scopedSlotsValue.put("attributes", "attributes");
        treeNode.setSlots(slotsValue);
        treeNode.setScopedSlots(scopedSlotsValue);
        return treeNode;
    }


    @Override
    public List<Map<String, Object>> getRubbishTypeInfoByIds(JSONObject deptIdsObj) {
        String[] deptIds = deptIdsObj.getString("deptIds").split(";");
        int i = 0;
        //考虑mybatis foreach的限制，所以定义参数格式为list内还是list
        List<List<String>> idsList = new ArrayList<List<String>>();
        List<String> idList = new ArrayList<String>();
        for (String deptId : deptIds) {
            //当id个数超出限制后，则新new一个list来存放
            if (i % 500 == 0 && i > 0) {
                idsList.add(idList);
                idList = new ArrayList<String>();
            }
            idList.add(deptId);
            i++;
        }
        idsList.add(idList);
        return mapper.getRubbishTypeInfoByIds(idsList);
    }


    /**
     * 通过分类编码查询分类
     *
     * @param deptCode 分类编码
     * @return 分类对象信息
     */
    @Override
    public RubbishType selectRubbishTypeByRubbishTypeCode(String deptCode) {
        return mapper.selectRubbishTypeByRubbishTypeCode(deptCode, BaseEntity.DEL_FLAG_NORMAL);
    }

    /**
     * 导出els
     *
     * @param sysRubbishType
     * @return
     */
    @Override
    public List<RubbishTypeEls> getRubbishTypexls(RubbishType sysRubbishType) {
        return mapper.getRubbishTypexls(sysRubbishType);
    }

    @Override
    public List<Map<String, Object>> getRubbishTypeStatement(RubbishType sysRubbishType) {
        return mapper.getRubbishTypeStatement(sysRubbishType);
    }

}
